import * as express from 'express';
import * as path from 'path';
import * as bodyParser from 'body-parser';
import * as cors from 'cors';
import * as health from 'express-ping';
import * as expressValidator from 'express-validator';

import { useExpressServer, useContainer, Action } from 'routing-controllers';
import { Container } from 'typedi';

import { setupLogging } from './Logging';
import { setupSwagger } from './Swagger';
import { setupAuth } from './Authentication';
import { setupLimit } from './Limiter';

export class ExpressConfig {

    app: express.Express;

    constructor() {
        this.app = express();
        this.app.use(cors());

        const env = this.app.get('env');
        if (env == 'dev' || env == 'test') {
            setupSwagger(this.app);
        }
        setupLogging(this.app);
        setupLimit(this.app);
        setupAuth(this.app);

        this.app.use(bodyParser.json());
        this.app.use(bodyParser.urlencoded({ extended: false }));
        this.app.use(health.ping());
        this.app.use(expressValidator());

        this.setupControllers();
    }

    setupControllers() {
        useContainer(Container);

        useExpressServer(this.app, {
            routePrefix: '/api',
            controllers: [path.resolve(__dirname, '../controllers/**/*')],
            middlewares: [path.resolve(__dirname, '../middlewares/*')],
            interceptors: [path.resolve(__dirname, '../interceptors/*')],
            validation: false,
            defaultErrorHandler: false,

            currentUserChecker: async (action: Action) => {
                const currentUser = action.request.user;
                return currentUser;
            },

            authorizationChecker: async (action: Action, permissions: string[]) => {
                if (!permissions.length) return true;

                // TODO: 权限控制
                const currentUser = action.request.user;
                let userPermissions: string[] = currentUser.permissions;

                if (permissions.find(permission => userPermissions.indexOf(permission) != -1))
                    return true;

                return false;
            }
        });
    }

}
